#pragma
#include <iostream>
#include <string>
#include <cstdio>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#define SIZE 1024
#define KEY_NUM 0x66
#define PATH "."
#define CREATE "create"
#define USE "user"
#define ERROR(str)   \
	{                \
		perror(str); \
		exit(1);     \
	}

using namespace std;
class Shm
{
private:
	void Create(int flg)
	{
		_shmid = shmget(_key, _size, flg);
		if (_shmid < 0)
		{
			ERROR("shmget");
		}
		printf("shmget success id:%d\n", _shmid);
	}
	void Attach()
	{
		_start_mem = shmat(_shmid, nullptr, 0);
		if ((long long)_start_mem < 0)
		{
			ERROR("shmat");
		}
	}
	void Destroy()
	{
		int m = shmdt(_start_mem);
		if (m < 0)
		{
			ERROR("shmdt");
		}
		int n = shmctl(_shmid, IPC_RMID, nullptr);
		if (n < 0)
		{
			ERROR("shmctl");
		}
	}

public:
	Shm(string path, int projid, string user)
		: _shmid(-1), _size(SIZE), _usertype(user)
	{
		_key = ftok(path.c_str(), projid);
		if (_key < 0)
		{
			ERROR("ftok");
		}
		printf("ftok success id:%d\n", _key);
		if (_usertype == CREATE)
			Create(IPC_CREAT | IPC_EXCL | 0666);
		else
			Create(IPC_CREAT);
		Attach();
	}
	void *VirtualAddr()
	{
		return _start_mem;
	}
	~Shm()
	{
		Destroy();
	}

private:
	int _shmid;
	int _size;
	int _key;
	string _usertype;
	void *_start_mem;
};